﻿using DAL;
using DAL.Dao;
using ExpressManagement.Areas.BackSys.ServiceTools;
using DAL.Models;
using MqTools;
using Newtonsoft.Json;
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using MqTools;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using AutoMapper;
using Microsoft.EntityFrameworkCore.Storage;
using ExpressManagement.Areas.BackSys.ServiceTools.Redis;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.EntityFrameworkCore;

namespace ExpressManagement.Areas.BackSys.Controllers
{
    [Area("BackSys")]
    [Authorize(Roles = "用户,管理员,快递员" )]
    public class BaseController : Controller
    {

        protected readonly IMapper mapper;
        protected readonly ILogger logger;
        protected static MQSender MqSender { get; private set; }
        protected static MQReceiver MqReceiver { get; private set; }

        protected const string ReceiverRoute = "#.{0}.{1}";
        protected const string SenderRoute = "{0}.{1}.{2}";
        /// <summary>
        /// 依次填入实体名称=》缓存类型=》序号=》用户类别
        /// </summary>
        protected const string RedisKeyFormatPage = "{0}.{1}.{2}.{3}";
        /// <summary>
        /// 依次填入实体名称=》缓存类型=》用户类别
        /// </summary>
        protected const string RedisKeyFormatTotalPage = "Mark.{0}.{1},{2}";

        protected readonly string EntityDeliveryman = "EntityDeliveryman";
        protected readonly string EntityUserInfo = "EntityUserInfo";
        protected readonly string EntityManager = "EntityManager";
        protected readonly string EntityBag = "EntityBag";
        protected readonly string EntityComplaint = "EntityComplaint";
        protected readonly string EntityMessage = "EntityMessage";


        protected readonly string TypePage = "TypePage";
        protected readonly string TypeItem = "TypePage";

        protected  ISession Sess { get; }
        public  string LoginType { get; set; }
        public  int UserId { get; set; }
        public  string UserName { get; set; }
        private readonly DbContextOptions<ExpressDBContext> _options;


        public static SignalRSender? SignalRSender { get; private set; }
        // GET: Base

        protected readonly RedisHelper _redis;
        //private readonly ExpressDBContext _dbContext;
        protected readonly IMemoryCache _memoryCache;
        protected readonly IMapper _mapper;
        public BaseController(IMemoryCache _memoryCache,RedisHelper redisHelper, ExpressDBContext _dbContext, IHttpContextAccessor httpContextAccessor, DbContextOptions<ExpressDBContext> dbContextOptions,IMapper mapper,SignalRSender signalRSender)
        {
            _mapper = mapper;
            _memoryCache = _memoryCache;
            DbEntity.BindContext(_dbContext, dbContextOptions);
            //this._dbContext = _dbContext;
            Sess = httpContextAccessor.HttpContext.Session;
            _redis = redisHelper;
            //_redis.Insert("demoTest","Pass");
            //this.mapper = mapper;
            //this.logger = logger;
            //var ok = httpContextAccessor.HttpContext.Items.TryGetValue("value", out object value);
             SignalRSender = signalRSender;
        }


        /// <summary>
        /// 填充待发送json,同时设置Redis缓存
        /// </summary>
        /// <param name="totalPages"></param>
        /// <param name="dataJson"></param>
        /// <param name="request_page"></param>
        /// <param name="set"></param>
        /// <param name="cacheEntity"></param>
        /// <param name="cacheType"></param>
        /// <param name="identity"></param>
        /// <param name="serializeStr"></param>
        protected void FillSetAndSaveCache(int totalPages, string dataJson, int request_page, IDictionary<string, string> set, string cacheEntity, string cacheType, string identity, out string serializeStr)
        {
            set.Add("totalPages", totalPages.ToString());
            set.Add("data", dataJson);
            serializeStr = JsonConvert.SerializeObject(set);
            SetCacheOnRedis<string>(cacheEntity, cacheType, request_page, identity, serializeStr);
        }


        /// <summary>
        /// 从redis中拿取缓存
        /// </summary>
        /// <param name="entity">实体名</param>
        /// <param name="cacheType">缓存类型</param>
        /// <param name="id">序号</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        protected T? GetCacheFromRedis<T>(string entity,string cacheType,int id,string identity)
        {
            string keyStr = string.Format(RedisKeyFormatPage, entity, cacheType, id, identity);
            return  _redis.Get<T>(keyStr);
        }

        /// <summary>
        /// 往redis设置缓存
        /// </summary>
        /// <param name="entity">实体名</param>
        /// <param name="cacheType">缓存类型</param>
        /// <param name="id">序号</param>
        /// <param name="identity">身份</param>
        /// <param name="value">数据</param>
        /// <returns></returns>
        protected void SetCacheOnRedis<T>(string entity, string cacheType, int id, string identity,T value)
        {

            var itemKey = string.Format(RedisKeyFormatPage, entity, cacheType, id, identity);
            _redis.Insert<T>(itemKey, value, RedisHelper.ExpireSeconds);
            var key = string.Format(RedisKeyFormatTotalPage, entity,cacheType,identity);
            var existCache = _redis.Get<HashSet<string>>(key);
            if (existCache == null)
            {
                  _redis.Insert<HashSet<string>>(key, new HashSet<string> { itemKey }, RedisHelper.ExpireSeconds);
            }
            else
            {

                existCache.Add(itemKey);
                _redis.Insert<HashSet<string>>(key, existCache, RedisHelper.ExpireSeconds);
            }
        }


        /// <summary>
        /// 从redis中删除缓存
        /// </summary>
        /// <param name="entity">实体名</param>
        /// <param name="cacheType">缓存类型</param>
        /// <param name="id">序号</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        protected void RemoveRedisCache(string entity, string cacheType, int id, string identity)
        {

            var itemKey = string.Format(RedisKeyFormatPage, entity, cacheType, id, identity);
            var key = string.Format(RedisKeyFormatTotalPage, entity);
            var cache = _redis.Get<HashSet<string>>(key);
            if (cache != null)
            {
                var set = _redis.Get<HashSet<string>>(key);
                set.Remove(itemKey);
                if (set.Count == 0) _redis.Remove(key);
                else  _redis.Insert<HashSet<string>>(key, set, RedisHelper.ExpireSeconds);
            }
        }
        /// <summary>
        /// 从redis中删除缓存
        /// </summary>
        /// <param name="entity">实体名</param>
        /// <param name="cacheType">缓存类型</param>
        /// <param name="identity">身份</param>
        /// <returns></returns>
        protected void RemoveRedisCacheEntity(string entity, string cacheType,string identity)
        {
            var keys = _redis.Get<HashSet<string>>(string.Format(RedisKeyFormatTotalPage, entity, cacheType, identity));
            if (keys != null)
            {
                foreach (var key in keys)
                {
                    _redis.Remove(key);
                }
            }
            _redis.Remove(string.Format(RedisKeyFormatTotalPage, entity, cacheType, identity));
        }

        protected   T?  GetObjectFromSession<T>(string key)
        {
            var sess = Sess;
            var jsonStr = sess.GetString(key);
            if (string.IsNullOrEmpty(jsonStr)) return default(T);
            return JsonConvert.DeserializeObject<T>(jsonStr);
        }

        protected void SetObjectInSession<T>(string key,T obj)
        {
            var sess = Sess;
            var jsonStr = JsonConvert.SerializeObject(obj);
            sess.SetString(key,jsonStr);
        }

        protected void SetStringInSession(string key, string value)
        {
            var sess = Sess;
            sess.SetString(key, value);
        }
        protected void SetInt32InSession(string key, int value)
        {
            var sess = Sess;
            sess.SetInt32(key, value);
        }
        public string? GetStringFromSession(string key)
        {
            return Sess.GetString(key);
        }

        public byte[]? GetByteFromSession(string key)
        {
            return Sess.Get(key);
        }
        public int? GetInt32FromSession(string key)
        {
            return Sess.GetInt32(key);
        }

        protected async void ReactCustomer(QueueMessage queueMessage)
        {
            string tips = string.Empty;
            string bagID = string.Empty;
            int complaintID = 0;

            MessageDaoimpl _impl = new MessageDaoimpl();
            
                string topic = string.Empty;
                switch (queueMessage.Action)
                {
                    case QueueMessage.ActionType.USER_REGISTER:
                        tips = string.Format("新用户注册{0}", queueMessage.User.Id);
                        topic = "用户";
                        break;
                    case QueueMessage.ActionType.BAG_REGISTRER:
                        tips = string.Format("新快递登记{0}", queueMessage.Bag.BagId);
                        topic = "快递";
                        bagID = queueMessage.Bag.BagId;
                        break;
                    case QueueMessage.ActionType.BAG_UPDATE:
                        tips = string.Format("快递更新{0}", queueMessage.Bag.BagId);
                        topic = "快递";
                        bagID = queueMessage.Bag.BagId;
                        break;
                    case QueueMessage.ActionType.BAG_DELETE:
                        tips = string.Format("快递删除{0}", queueMessage.Bag.BagId);
                        topic = "快递";
                        bagID = queueMessage.Bag.BagId;
                        break;
                    case QueueMessage.ActionType.COMPLAINT_REPLY:
                        tips = string.Format("投诉有了回复{0}", queueMessage.Complaint.Id);
                        topic = "投诉";
                        complaintID = queueMessage.Complaint.Id;
                        break;
                    case QueueMessage.ActionType.COMPLAINT_SUBMIT:
                        tips = string.Format("有新的投诉上传{0}", queueMessage.Complaint.Id);
                        topic = "投诉";
                        complaintID = queueMessage.Complaint.Id;
                        break;
                    case QueueMessage.ActionType.COMPLAINT_DELETE:
                        tips = string.Format("有一则投诉删除{0}", queueMessage.Complaint.Id);
                        topic = "投诉";
                        complaintID = queueMessage.Complaint.Id;
                        break;
                    case QueueMessage.ActionType.COMPLAINT_UPDATE:
                        tips = string.Format("有一则投诉更新信息{0}", queueMessage.Complaint.Id);
                        topic = "投诉";
                        complaintID = queueMessage.Complaint.Id;
                        break;
                    default:
                        break;
                }
                var message = _impl.Add(new Message()
                {
                    Info = tips,
                    UserId = queueMessage.User.Id,
                    Topic = topic,
                    AddTime = DateTime.Now,
                    ComplaintId = complaintID,
                    BagId = bagID
                });
                await SignalRSender.SendSysToOneByUserId(queueMessage.User.Id,JsonConvert.SerializeObject(message));
                Debug.WriteLine(tips);
            
               
        }
       

        protected void ResetMQLink()
        {
            if (MqReceiver.Connection.IsOpen) MqReceiver.Connection.Abort();
        }
        protected  async void  ReactCompany(QueueMessage queueMessage)
        {
            string tips = string.Empty;
            string topic = string.Empty;
            string bagID = string.Empty;
            int complaintID = 0;
            MessageDaoimpl _impl = new MessageDaoimpl();
            
                switch (queueMessage.Action)
                {
                    case QueueMessage.ActionType.USER_REGISTER:
                        tips = string.Format("新用户注册{0}", queueMessage.User.Id);
                        topic = "用户";
                        break;
                    case QueueMessage.ActionType.BAG_REGISTRER:
                        tips = string.Format("新快递注册{0}", queueMessage.Bag.BagId);
                        bagID = queueMessage.Bag.BagId;
                        topic = "快递";
                        break;
                    case QueueMessage.ActionType.BAG_UPDATE:
                        tips = string.Format("快递更新{0}", queueMessage.Bag.BagId);
                        bagID = queueMessage.Bag.BagId;
                        topic = "快递";
                        break;
                    case QueueMessage.ActionType.BAG_DELETE:
                        tips = string.Format("快递删除{0}", queueMessage.Bag.BagId);
                        bagID = queueMessage.Bag.BagId;
                        topic = "快递";
                        break;
                    case QueueMessage.ActionType.COMPLAINT_SUBMIT:
                        tips = string.Format("有新的投诉上传{0}", queueMessage.Complaint.Id);
                        complaintID = queueMessage.Complaint.Id;
                        topic = "投诉";
                        break;
                    case QueueMessage.ActionType.COMPLAINT_DELETE:
                        tips = string.Format("有一则投诉删除{0}", queueMessage.Complaint.Id);
                        complaintID = queueMessage.Complaint.Id;
                        topic = "投诉";
                        break;
                    case QueueMessage.ActionType.COMPLAINT_UPDATE:
                        tips = string.Format("有一则投诉更新信息{0}", queueMessage.Complaint.Id);
                        complaintID = queueMessage.Complaint.Id;
                        topic = "投诉";
                        break;
                    default:
                        break;
                }
                _impl.Add(new Message
                {
                    Info = tips,
                    UserId = queueMessage.User.Id,
                    Topic = topic,
                    AddTime = DateTime.Now,
                    ComplaintId = complaintID,
                    BagId = bagID
                });
                await SignalRSender.SendSysToGroup("Company",tips.ToString());
                Debug.WriteLine(tips);
            
         
           
            //Debug.WriteLine(string.Format(tipTemplate, tips));
            //Response.Write(string.Format(tipTemplate, tips));
            //Response.End();
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {

            //base.OnActionExecuting(filterContext);
            if (GetInt32FromSession("senderRows") == null)
            {
                SetInt32InSession("senderRows", 10);
            }

            if (GetInt32FromSession("senderPage") == null)
            {
                SetInt32InSession("senderPage", 1);
            }
            if (GetInt32FromSession("getterRows") == null)
            {
                SetInt32InSession("getterRows", 10);
            }
            if (GetInt32FromSession("getterPage") == null)
            {
                SetInt32InSession("getterPage", 1);
            }
            if (GetInt32FromSession("bagRows") == null)
            {
                SetInt32InSession("bagRows", 10);
            }
            if (GetInt32FromSession("bagPage") == null)
            {
                SetInt32InSession("bagPage", 1);
            }
            if (GetInt32FromSession("complaintRows") == null)
            {
                SetInt32InSession("complaintRows", 10);
            }
            if (GetInt32FromSession("complaintPage") == null)
            {
                SetInt32InSession("complaintPage", 1);
            }
            if (GetInt32FromSession("deliverymanRows") == null)
            {
                SetInt32InSession("deliverymanRows", 10);
            }
            if (GetInt32FromSession("deliverymanPage") == null)
            {
                SetInt32InSession("deliverymanPage", 1);
            }
            if (string.IsNullOrEmpty(GetStringFromSession("managerRows")))
            {
                SetInt32InSession("managerRows", 10);
            }
            if (string.IsNullOrEmpty(GetStringFromSession("managerPage")))
            {
                SetInt32InSession("managerPage", 1);
            }
            if (GetInt32FromSession("messageRows") == null)
            {
                SetInt32InSession("messageRows", 10);
            }
            if (GetInt32FromSession("messagePage") == null)
            {
                SetInt32InSession("messagePage", 0);
            }
            if (GetInt32FromSession("userRows") == null)
            {
                SetInt32InSession("userRows", 10);
            }
            if (GetInt32FromSession("userPage") == null)
            {
                SetInt32InSession("userPage", 1);
            }
            LoginType = GetStringFromSession("loginType");
           
            if (string.IsNullOrEmpty(LoginType))
            {
                //重定向至登录页面
                filterContext.Result = RedirectToAction("Login", "Home");
                return;
            }
      
            UserId = Convert.ToInt16(GetStringFromSession("userId"));
            if (MqSender == null)
            {
                MqSender = new MQSender(Resource.HostName, Resource.VirtualHost, Resource.UserName, Resource.Password, Resource.Exchange, ExchangeType.Topic);
            }
            if (MqReceiver == null)
            {
                MqReceiver = new MQReceiver(Resource.HostName, Resource.VirtualHost, Resource.UserName, Resource.Password, Resource.Exchange, ExchangeType.Topic);
                MqReceiver.Bind(Resource.CustomerBagQueue, Resource.CustomerBagRoute, ReactCustomer);
                MqReceiver.Bind(Resource.CustomerComplaintQueue, Resource.CustomerComplaintRoute, ReactCustomer);
                MqReceiver.Bind(Resource.CompanyUserQueue, Resource.CompanyUserRoute, ReactCompany);
                MqReceiver.Bind(Resource.CompanyComplaintQueue, Resource.CompanyComplaintRoute, ReactCompany);
                MqReceiver.Bind(Resource.CompanyBagQueue, Resource.CompanyBagRoute, ReactCompany);

            }

        }

    }
}